#include "curtain.h"
#include "usart1.h"
#include "sys.h"
#include "led.h"
#include "font.h"
#include "tim5.h"
#include "w25qxx.h"

uint16_t tmp_scan_list[10] = {0};
uint16_t has_tmp_scan_list = 0;
uint16_t is_old_curtain = 0;

// 如果没收到消息,会返回0x0000, 实际中这样会有一定的容错能力,偶尔一次通讯出错不会引起不必要的后果
uint16_t curtain_read_light_status(uint8_t id, uint16_t led_mask)
{
    *TxCmdID = id;
    NewMsgFlag = RxMsgBackup = 0;
    *TxCmdData = has_tmp_scan_list ? tmp_scan_list[id - 1] : led_mask;
    usart1_transmit_curtain_cmd();
    if (led_mask == 0)
    {
        Delay_us_With_Break_by_Value(CURTAIN_ONLINE_REPLAY_US, &NewMsgFlag);
    }
    else
    {
        Delay_us_With_Break_by_Value(CURTAIN_R_SCAN_US, &NewMsgFlag);
    }
    return RxMsgBackup;
}

// 查询光线撞断的数量,如果只询问4条光线,最多返回4
uint16_t curtain_blocked_light_count(uint8_t id, uint16_t led_mask)
{
    uint16_t result = curtain_read_light_status(id, led_mask);
    uint16_t count = 0;
    for (uint8_t i = 0; i < 16; i++)
    {
        count += (result & 0x01);
        result >>= 1;
    }
    return count;
}

// 发射光栅在线与否
uint8_t curtain_is_send_online(uint8_t id)
{
    *TxCmdID = id;
    NewMsgFlag = RxMsgBackup = 0;
    *TxCmdData = is_old_curtain ? 0x0001 : 0x0000; // 旧传感器不能发送0x0000,程序bug原因还未查明
    usart1_transmit_curtain_cmd();
    Delay_us_With_Break_by_Value(CURTAIN_ONLINE_REPLAY_US, &NewMsgFlag);
    return NewMsgFlag;
}

// 接收光栅在线与否
uint8_t curtain_is_recv_online(uint8_t id)
{
    *TxCmdID = id;
    NewMsgFlag = RxMsgBackup = 0;
    *TxCmdData = 0x0001;
    usart1_transmit_curtain_cmd();
    Delay_us_With_Break_by_Value(CURTAIN_ONLINE_REPLAY_US, &NewMsgFlag);
    return NewMsgFlag;
}

// 光栅在线数量
/*
    如果收到信息，马上发下一条信息，那么发出的信号，与反射的信号叠加，会让
    接收端的TVS超过6.8V,然后TVS的电压就会被拉低，导致485波形会被拉低，导致
    异常信号
    1us信号传输30m,延迟10us,反射信号会完全消失
*/
uint8_t curtain_online_count(uint8_t max_id)
{
    uint8_t count = 0;
    for (uint8_t i = 1; i <= max_id; i++)
    {
        count += curtain_is_send_online(i);
        Delay_us(10);
        count += curtain_is_recv_online(i);
        Delay_us(10);
    }
    return count;
}

// 从flash中读取scanlist
uint8_t curtains_temp_read_scanlist(uint8_t max_id)
{
    uint8_t flag = 0;
    flash_read_data(TEMP_SCANLIST_FLAG, &flag, 1); // 读取标示
    if (flag == HAS_TEMP_SCANLIST)                 // 有临时扫描列表
    {
        flash_read_data(TEMP_SCANLIST_ADDR, (uint8_t *)tmp_scan_list, max_id * 2);
        has_tmp_scan_list = 1;
        return 1;
    }
    else
    {
        has_tmp_scan_list = 0;
        return 0;
    }
}
